package com.liu.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.npc.entity.base.NpcBasicsInfo;
import com.liu.npc.entity.base.NpcOperateRelation;
import com.liu.npc.service.INpcBasicsInfoService;
import com.liu.npc.service.INpcOperateRelationService;
import com.liu.operate.entity.base.OperateDetailInfo;
import com.liu.operate.entity.base.OperateInfo;
import com.liu.operate.service.IOperateDetailInfoService;
import com.liu.operate.service.IOperateInfoService;
import com.liu.user.entity.base.UserBasicsInfo;
import com.liu.user.entity.base.UserOperateInfo;
import com.liu.user.entity.dto.UserBasicsInfoDTO;
import com.liu.user.entity.dto.UserOperateInfoDTO;
import com.liu.user.entity.qo.UserOperateQO;
import com.liu.user.mapper.UserOperateInfoMapper;
import com.liu.user.service.IUserBasicsInfoService;
import com.liu.user.service.IUserOperateInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 用户操作信息表 服务实现类
 * </p>
 *
 * @author LiuChengLong
 * @since 2023-03-12
 */
@Service
public class UserOperateInfoServiceImpl extends ServiceImpl<UserOperateInfoMapper, UserOperateInfo> implements IUserOperateInfoService {

    /**
     * 操作信息服务
     */
    @Resource
    private IOperateInfoService operateInfoService;

    /**
     * 用户信息服务
     */
    @Resource
    private IUserBasicsInfoService userBasicsInfoService;

    /**
     * npc信息服务
     */
    @Resource
    private INpcBasicsInfoService npcBasicsInfoService;

    /**
     * npc操作信息服务
     */
    @Resource
    private INpcOperateRelationService npcOperateRelationService;

    /**
     * 操作子信息服务
     */
    @Resource
    private IOperateDetailInfoService operateDetailInfoService;

    @Override
    public UserOperateInfoDTO userOperateInfo(UserOperateQO userOperateQO) {
        UserOperateInfoDTO userOperateInfoDTO = new UserOperateInfoDTO();
        // 获取操作信息
        QueryWrapper<OperateInfo> operateInfoQueryWrapper = new QueryWrapper<>();
        operateInfoQueryWrapper.last("ORDER BY Rand() limit 1");
        OperateInfo operateInfo = operateInfoService.getOne(operateInfoQueryWrapper);

        // 根据操作主信息id获取操作详情
        QueryWrapper<OperateDetailInfo> operateDetailInfoQueryWrapper = new QueryWrapper<>();
        operateDetailInfoQueryWrapper.eq("operate_id", operateInfo.getId());
        List<OperateDetailInfo> operateDetailInfoList = operateDetailInfoService.list(operateDetailInfoQueryWrapper);

        // 获取当前用户信息
        UserBasicsInfo userBasicsInfo = userBasicsInfoService.getById(userOperateQO.getUserId());

        // 用户操作信息列表
        List<UserOperateInfo> userOperateInfoList = new ArrayList<>();

        // 拼接操作记录
        StringBuilder result = new StringBuilder();
        result.append(operateInfo.getOperateName()).append(operateInfo.getOperateInfo()).append(" → ");
        for (int i = 0; i < operateDetailInfoList.size(); i++) {
            OperateDetailInfo operateDetailInfo = operateDetailInfoList.get(i);

            // 拼接操作信息内容
            String operateRecordResult = this.splicingOperationInfo(operateDetailInfo);
            if (i == operateDetailInfoList.size() - 1) {
                result.append(operateRecordResult).append("。");
            } else {
                result.append(operateRecordResult).append(" | ");
            }

            // 组装用户操作信息
            UserOperateInfo userOperateInfo = new UserOperateInfo();
            userOperateInfo.setUserId(userOperateQO.getUserId());
            userOperateInfo.setOperateRecord(operateInfo.getOperateName() + operateInfo.getOperateInfo() + " → " + operateRecordResult);
            userOperateInfo.setOperator(operateDetailInfo.getOperator());
            userOperateInfo.setAddOrSubData(operateDetailInfo.getAddOrSubData());
            userOperateInfo.setOperateObject(operateDetailInfo.getOperateObject());
            userOperateInfoList.add(userOperateInfo);

            // 计算用户操作后信息
            this.calHpAndMoney(operateDetailInfo, userBasicsInfo);
        }

        // 判断角色当前HP是否低于0，低于0则死亡，重置角色
        if (userBasicsInfo.getNowHP() <= 0) {
            result = new StringBuilder();
            result.append(operateInfo.getOperateName()).append("，生命值低于0被击杀").append(" → 角色重置");
            userBasicsInfo.setGameMoney(100);
            userBasicsInfo.setNowHP(100);
            userBasicsInfo.setMaxHP(100);
            UserOperateInfo userOperateInfo = new UserOperateInfo();
            userOperateInfo.setUserId(userOperateQO.getUserId());
            userOperateInfo.setOperateRecord(result.toString());
            userOperateInfo.setOperator("-");
            userOperateInfo.setAddOrSubData(0);
            userOperateInfo.setOperateObject(0);
            userOperateInfoList.add(userOperateInfo);
        }

        // 插入用户操作记录表
        super.saveBatch(userOperateInfoList);

        // 修改用户主表信息
        userBasicsInfoService.updateById(userBasicsInfo);

        userOperateInfoDTO.setOperateInfo(result.toString());
        UserBasicsInfoDTO userBasicsInfoDTO = BeanUtil.copyProperties(userBasicsInfo, UserBasicsInfoDTO.class);
        userOperateInfoDTO.setNewUserInfo(userBasicsInfoDTO);

        return userOperateInfoDTO;
    }

    /**
     * 拼接操作信息
     * @param operateDetailInfo 操作信息
     * @return 操作信息
     */
    public String splicingOperationInfo(OperateDetailInfo operateDetailInfo){
        Integer operateObject = operateDetailInfo.getOperateObject();
        Integer addOrSubData = operateDetailInfo.getAddOrSubData();
        String operator = operateDetailInfo.getOperator();
        Integer operateType = operateDetailInfo.getOperateType();
        String operateObjectName = null;
        switch (operateType){
            case 0:
            case 1:
                switch (operateObject){
                    case 0:
                        operateObjectName = "生命";
                        break;
                    case 1:
                        operateObjectName = "金币";
                        break;
                }
                break;
            case 2:
            case 3:
                switch (operateObject){
                    case 0:
                        operateObjectName = "生命上限";
                        break;
                    case 1:
                        operateObjectName = "金币上限";
                        break;
                }
                break;
        }

        return operator + addOrSubData + operateObjectName;
    }

    /**
     * 计算用户HP和金币
     * @param operateDetailInfo 操作子信息
     * @param userBasicsInfo 用户信息
     */
    public void calHpAndMoney(OperateDetailInfo operateDetailInfo, UserBasicsInfo userBasicsInfo){
        int gameMoney = userBasicsInfo.getGameMoney();
        int maxHP = userBasicsInfo.getMaxHP();
        int nowHP = userBasicsInfo.getNowHP();
        Integer operateType = operateDetailInfo.getOperateType();
        Integer operateObject = operateDetailInfo.getOperateObject();
        Integer addOrSubData = operateDetailInfo.getAddOrSubData();
        switch (operateType){
            case 0:
                switch (operateObject){
                    case 0:
                        nowHP = nowHP + addOrSubData;
                        if (nowHP >= maxHP) {
                            nowHP = maxHP;
                        }
                        break;
                    case 1:
                        gameMoney = gameMoney + addOrSubData;
                        break;
                }
                break;
            case 1:
                switch (operateObject){
                    case 0:
                        nowHP = nowHP - addOrSubData;
                        break;
                    case 1:
                        gameMoney = gameMoney - addOrSubData;
                        break;
                }
                break;
            case 2:
                if (operateObject == 0) {
                    maxHP = maxHP + addOrSubData;
                }
                break;
        }
        userBasicsInfo.setNowHP(nowHP);
        userBasicsInfo.setMaxHP(maxHP);
        userBasicsInfo.setGameMoney(gameMoney);
    }

    @Override
    public void getNpcOperate(Integer userId, UserOperateInfoDTO userOperateInfoDTO){
        Random random = new Random();
        int nextInt = random.nextInt(9);
        if (nextInt <= 3){
            List<NpcBasicsInfo> npcBasicsInfoList = npcBasicsInfoService.list();
            if (CollUtil.isNotEmpty(npcBasicsInfoList)){
                // 将list随机排序，获取随机npc
                Collections.shuffle(npcBasicsInfoList);
                String npcName = npcBasicsInfoList.get(0).getNpcName();
                Integer npcId = npcBasicsInfoList.get(0).getId();
                QueryWrapper<NpcOperateRelation> wrapper = new QueryWrapper<>();
                wrapper.eq("npc_id", npcId);
                List<NpcOperateRelation> npcOperateRelationList = npcOperateRelationService.list(wrapper);
                if (CollUtil.isNotEmpty(npcOperateRelationList)){
                    // 将list随机排序，获取随机操作
                    Collections.shuffle(npcOperateRelationList);
                    Integer operateId = npcOperateRelationList.get(0).getOperateId();
                    // 获取操作信息
                    OperateInfo operateInfo = operateInfoService.getById(operateId);
                    // 获取操作详情
                    QueryWrapper<OperateDetailInfo> operateDetailInfoQueryWrapper = new QueryWrapper<>();
                    operateDetailInfoQueryWrapper.eq("operate_id", operateInfo.getId());
                    List<OperateDetailInfo> operateDetailInfoList = operateDetailInfoService.list(operateDetailInfoQueryWrapper);

                    // 拼接操作记录
                    StringBuilder result = new StringBuilder();
                    result.append(operateInfo.getOperateName()).append(" → ");

                    // 获取当前用户信息
                    UserBasicsInfo userBasicsInfo = userBasicsInfoService.getById(userId);

                    // 用户操作信息列表
                    List<UserOperateInfo> userOperateInfoList = new ArrayList<>();
                    for (int i = 0; i < operateDetailInfoList.size(); i++) {
                        OperateDetailInfo operateDetailInfo = operateDetailInfoList.get(i);
                        String operateRecord = this.splicingOperationInfo(operateDetailInfo);
                        if (i == operateDetailInfoList.size() - 1) {
                            result.append(operateRecord).append("。");
                        } else {
                            result.append(operateRecord).append(" | ");
                        }
                        UserOperateInfo userOperateInfo = new UserOperateInfo();
                        userOperateInfo.setUserId(userId);
                        userOperateInfo.setOperateRecord(operateRecord);
                        userOperateInfo.setOperator(operateDetailInfo.getOperator());
                        userOperateInfo.setAddOrSubData(operateDetailInfo.getAddOrSubData());
                        userOperateInfo.setOperateObject(operateDetailInfo.getOperateObject());
                        userOperateInfoList.add(userOperateInfo);

                        // 计算用户操作后信息
                        this.calHpAndMoney(operateDetailInfo, userBasicsInfo);
                    }

                    // 判断角色当前HP是否低于0，低于0则死亡，重置角色
                    if (userBasicsInfo.getNowHP() <= 0) {
                        result = new StringBuilder();
                        result.append(operateInfo.getOperateName()).append("，生命值低于0被击杀").append(" → 角色重置");
                        userBasicsInfo.setGameMoney(100);
                        userBasicsInfo.setNowHP(100);
                        userBasicsInfo.setMaxHP(100);
                        UserOperateInfo userOperateInfo = new UserOperateInfo();
                        userOperateInfo.setUserId(userId);
                        userOperateInfo.setOperateRecord(result.toString());
                        userOperateInfo.setOperator("-");
                        userOperateInfo.setAddOrSubData(0);
                        userOperateInfo.setOperateObject(0);
                        userOperateInfoList.add(userOperateInfo);
                    }

                    // 修改用户主表信息
                    userBasicsInfoService.updateById(userBasicsInfo);

                    // 插入用户操作记录表
                    super.saveBatch(userOperateInfoList);

                    userOperateInfoDTO.setNpcOperateInfo("偶遇NPC：" + npcName + result);
                    UserBasicsInfoDTO userBasicsInfoDTO = BeanUtil.copyProperties(userBasicsInfo, UserBasicsInfoDTO.class);
                    userOperateInfoDTO.setNewUserInfo(userBasicsInfoDTO);
                }
                userOperateInfoDTO.setNpcOperateInfo("偶遇NPC：" + npcName + "无事发生。");
            }
        }
    }
}
